﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using ArgusLib.Fractals;

namespace Fraktalysator.Forms
{
	partial class FractalParameterForm : ToolForm
	{
		#region Private Fields
		IFractalProvider[] fractalProviders;
		IFractalProvider selectedFractalProvider;
		#endregion

		#region Properties
		private IFractalParameterInputControl inputControl;
		public IFractalParameterInputControl InputControl
		{
			get { return this.inputControl; }
			private set
			{
				this.inputControl = value;
				this.pParameterInputControl.Controls.Clear();
				this.pParameterInputControl.Controls.Add(this.inputControl.Control);
			}
		}

		public Type FractalType
		{
			get
			{
				if (this.selectedFractalProvider == null)
					return null;
				return this.selectedFractalProvider.FractalType;
			}
		}

		//public ArgusLib.Fractals.IFractal Fractal { get; private set; }
		#endregion

		#region Constructors
		public FractalParameterForm()
			:base()
		{
			InitializeComponent();
		}
		#endregion

		#region Public Methods
		public IFractal GetFractal()
		{
			if (this.selectedFractalProvider == null)
				return null;

			IFractal fractal = this.selectedFractalProvider.GetFractal();
			fractal.Parameter = this.InputControl.Parameter;
			return fractal;
		}

		public void SelectFractal(IFractal fractal)
		{
			Type fType = fractal.GetType();
			for (int i = 0; i < this.fractalProviders.Length; i++)
			{
				if (this.fractalProviders[i].FractalType == fType)
				{
					this.cbFractal.SelectedIndex = i;
					break;
				}
			}
			this.InputControl.Parameter = fractal.Parameter;
		}
		#endregion

		#region Non-Public Methods
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			this.InitializeFractalComboBox();
			//this.OnCalculationRequested();
		}

		private void bCalculate_Click(object sender, EventArgs e)
		{
			this.OnCalculationRequested();
		}

		private void InitializeFractalComboBox()
		{
			Assembly assembly = Assembly.GetAssembly(typeof(IFractalProvider));
			this.fractalProviders = assembly.GetInterfaceImplementations<IFractalProvider>();

			this.cbFractal.Items.Clear();
			int index = 0;
			for (int i = 0; i < this.fractalProviders.Length; i++)
			{
				this.cbFractal.Items.Add(this.fractalProviders[i].FractalName);
				if (this.fractalProviders[i] is FractalProviders.MandelbrotSetProvider)
					index = i;
			}
			this.cbFractal.SelectedIndex = index;
		}

		private void cbFractal_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (this.cbFractal.SelectedIndex < 0)
				return;
			int width = 450;
			int height = 450;
			if (this.InputControl != null)
			{
				ArgusLib.Fractals.IParameter oldPara = this.InputControl.Parameter;
				width = oldPara.PixelWidth;
				height = oldPara.PixelHeight;
			}
			IFractalProvider fProvider = this.fractalProviders[this.cbFractal.SelectedIndex];
			this.InputControl = fProvider.GetParameterInputControl();
			this.InputControl.Control.Dock = DockStyle.Fill;
			this.InputControl.Parameter = fProvider.GetStandardParameter(width, height);
			//this.Fractal = fProvider.GetFractal();
			this.selectedFractalProvider = fProvider;
		}
		#endregion

		#region Eventhandling
		public event EventHandler CalculationRequested;

		private void OnCalculationRequested()
		{
			if (this.CalculationRequested != null)
			{
				this.CalculationRequested(this, EventArgs.Empty);
			}
		}
		#endregion
	}
}
